﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Linq;
using System.Windows.Forms;
using ConcreteMappersAndObjects.DomainObjects;
using ExaminationTT.Control;
using System.Threading;
using ExaminationTT.Model;
using ExaminationTT.Rule;
//------------------


namespace ExaminationTT.View
{
    public partial class Board : Form
    {
        private Range r;
        private BackgroundWorker _bgw;
        //Lista de exames a validar
        private ArrayList _pending;
        /// <summary>
        /// Dicionario de exames já verificados com os conflitos associados
        /// </summary>
        //private Dictionary<IExam, List<IConflit>> _checked;
        /// <summary>
        /// to support grid painting
        /// </summary>
        private List<DateTime> _days;
        private HostApplication _host;
        /// <summary>
        /// List of rules
        /// </summary>
        private List<ViewRule> _rules;

        /// <summary>
        /// current selected exam
        /// </summary>
        private IExam _currentExam;
        /// <summary>
        /// All conflits
        /// </summary>
        /// 
        private List<IConflict> _allConflitList;
        private BindingSource _allConflitsDataSource;
        private BindingSource _currentExamConflitsDataSource;
        private BindingSource _currentExamRoomsSelectedDataSource;
        private Dictionary<IExam, DataGridViewCell> _exam_cell;
        private BindingSource _currentExamRooms;

        public Board(HostApplication host, IEnumerable<ViewRule> rules)
        {
            _host = host;
            InitializeComponent();
            _board.ContextMenuStrip = _ctxmenu_exams;
            _bgw = new BackgroundWorker();
            _pending = new ArrayList();
            _pending = ArrayList.Synchronized(_pending);
            //_checked = new Dictionary<IExam, List<IConflit>>();
            _days = new List<DateTime>();
            _allConflitList = new List<IConflict>();
            _rules = rules.ToList();
            _allConflitsDataSource = new BindingSource();
            _currentExamConflitsDataSource = new BindingSource();
            _currentExamRoomsSelectedDataSource = new BindingSource();
            _currentExamRooms = new BindingSource();
            _dgv_examConflits.SetColumns();
            _dgv_allConflits.SetColumns();
            _dgv_roomsList.SetColumns();
            _allConflitsDataSource.DataSource = _host.GetAllConflits().ToList();
            _dgv_allConflits.DataSource = _allConflitsDataSource;
            _dgv_examConflits.DataSource = _currentExamConflitsDataSource;
            _dgv_roomsList.DataSource = _currentExamRoomsSelectedDataSource;
            _exam_cell = new Dictionary<IExam, DataGridViewCell>();
            //_checked = _host.GetScheduledExams();
            //------------------
            InitializeWorker();
            IEnumerable<ExamSeason> listOfSeasons = MapperControl.GetAllSeasons();
            if (listOfSeasons.Count() == 0)
            {
                //TODO notify user to build seasons;
                MessageBox.Show("Não estão épocas definidas", this.Text);

            }
            //TODO MV - add checkbox datasource
            _cbx_seasonSelection.DataSource = listOfSeasons;
            _cbx_seasonSelection.DisplayMember = "Description";
            _cbx_seasonSelection.SelectedItem = 0;



        }

        /// <summary>
        /// Initializes background worker thread
        /// </summary>
        private void InitializeWorker()
        {
            _bgw.WorkerSupportsCancellation = false;
            _bgw.WorkerReportsProgress = true;
            _bgw.DoWork += WorkerDoWork;
            _bgw.ProgressChanged += WorkerReport;
            _bgw.RunWorkerAsync();
        }
        /// <summary>
        /// callback to report work from background worker thread
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void WorkerReport(object sender, ProgressChangedEventArgs e)
        {
            if (e.ProgressPercentage == 100)
            {
                ((MainForm)this.MdiParent).SetStatus("");
                PaintCellBackgroung((IExam)e.UserState);
                //_allConflitList.AddRange(_host.SetExam((IExam)e.UserState));
                LogTextboxRefresh();
            }
            if (e.ProgressPercentage == 0)
            {
                ((MainForm)this.MdiParent).SetStatus("Regras a processar.");
            }
        }
        /// <summary>
        /// Do work from background worker thread - validates exams, association with conflits
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void WorkerDoWork(object sender, DoWorkEventArgs e)
        {
            while (true)
            {
                //se a lista de exames pendentes estiver vazia bloquio me
                if (_pending.Count == 0)
                {
                    try
                    {
                        lock (_pending)
                        {
                            //MessageBox.Show("No Task");
                            Monitor.Wait(_pending);
                        }
                    }
                    catch (ThreadAbortException ta)
                    {
                        MessageBox.Show(ta.ToString());
                    }
                }
                #region toDelete
                /*
                        //var tmpDic = new Dictionary<Exam, List<IConflit>>();
                        foreach (Exam pendingExam in _pending)
                        {
                            //var tmpDic = new Dictionary<Exam, IConflit>();
                            //se o exame n existir no dicionario adiciono
                            if (!_checked.ContainsKey(pendingExam)) _checked.Add(pendingExam, new List<IConflit>());
                            foreach (Exam checkedExam in _checked.Keys)
                            {
                                if (pendingExam.Equals(checkedExam)) continue;
                                //if(!tmpDic.ContainsKey(exam)) tmpDic.Add(exam,null);
                                //if (tmpDic[exam] == null)
                                //{
                                //    tmpDic[exam] = new List<IConflit>();
                                //}
                                IConflit conflit;
                                foreach (ViewRule rule in _rules.Where(rule => rule.Active))
                                {
                                    conflit = rule.Rule.EnforceRule(pendingExam, checkedExam);
                                    if (conflit != null)
                                    {
                                        _checked[pendingExam].Add(conflit);
                                        _checked[checkedExam].Add(conflit);

                                        _allConflitList.Add(conflit);
                                    }
                                    //_allConflitsDataSource.Add(conflit);
                                }
                                _bgw.ReportProgress(0, null);
                            }
                            //_checked.Add(exam, null);
                        }
                        //foreach (var ex in tmpDic)
                        //{
                        //    if (_checked[ex.Key] == null)
                        //    {
                        //        _checked[ex.Key] = new List<IConflit>();
                        //    }
                            //_checked.Add(exam, null);
                        //}
                        //foreach (var ex in tmpDic)
                        //{
                        //    if (_checked[ex.Key] == null)
                        //    {
                        //        _checked[ex.Key] = new List<IConflit>();
                        //    }
                        //    _checked[ex.Key].AddRange(ex.Value);
                        //}
                        _pending.RemoveAll(pendingExam => true);
                     */
                #endregion
                _bgw.ReportProgress(0, null);
                IExam exam = (IExam)_pending[0];
                _pending.RemoveAt(0);
                try
                {
                    _host.SetExam(exam);
                    //_allConflitList.AddRange(_host.SetExam(exam));
                    //Thread.Sleep(10000);
                }
                catch (InvalidOperationException ex)
                {
                    MessageBox.Show(ex.Message);
                }/*
                List<IConflit> conflit = new List<IConflit>();
                try
                {
                    conflit.AddRange(_host.SetExam(exam));
                }
                catch (InvalidOperationException ex)
                {
                    MessageBox.Show(ex.Message);
                }
                if (conflit.Count != 0)
                {
                    _checked = _host.GetScheduledExams();
                }*/
                //_allConflitsDataSource.DataSource = _host.GetAllConflits();
                _bgw.ReportProgress(100, exam);
            }
        }

        private class Range
        {
            public DateTime StartDate { get; set; }
            public DateTime StopDate { get; set; }
        }

        private void PaintBoard(IExamSeason season)
        {
            if (season.StartSeason > season.EndSeason) { throw new InvalidOperationException(); }
            this.SuspendLayout();
            _board.Columns.Clear();
            _board.Rows.Clear();
            _exam_cell.Clear();
            r = new Range { StartDate = season.StartSeason, StopDate = season.EndSeason };
            IEnumerable<ICUnit> luc = _host.GetAllCUnits();// MapperControl.GetAllCUnit();
            _board.ColumnCount = (r.StopDate - r.StartDate).Days + 1;
            _board.Columns[0].Name = "UC";
            _board.Columns[0].SortMode = DataGridViewColumnSortMode.NotSortable;
            _board.Columns["UC"].Frozen = true;
            DateTime initial = r.StartDate;
            for (int i = 1; i < _board.ColumnCount; i++)
            {
                _days.Add(initial);
                _board.Columns[i].Name = initial.ToString("ddd, MM/dd");
                _board.Columns[i].HeaderCell.ToolTipText = r.StartDate.AddDays(i - 1).Date.ToString("MM / dd / yyyy");
                _board.Columns[i].Tag = initial;
                _board.Columns[i].SortMode = DataGridViewColumnSortMode.NotSortable;
                initial = initial.AddDays(1);
            }
            var group = from s in
                            (from uc in luc
                             group uc by uc.Semesters.First().Semester.Number
                                 into map
                                 select new { map.Key, Value = map.ToList() })
                        orderby s.Key ascending
                        select s;
            foreach (var s in group)
            {
                
                _board.Rows.Add(s.Key + "º Semestre");
                for (int i = 1; i < _board.Columns.Count; i++)
                {
                    _board[i, _board.Rows.Count - 1].Style.BackColor = Color.Gray;
                }
                foreach (var v in s.Value)
                {
                    _board.Rows[_board.Rows.Add(v.Acronym)].Tag = v;
                    //TODO MV - get exams
                    for (int i = 1; i < _board.Columns.Count; i++)
                    {
                        DateTime dt = (DateTime)_board.Columns[i].Tag;
                        if (dt.DayOfWeek == DayOfWeek.Saturday || dt.DayOfWeek == DayOfWeek.Sunday)
                        {
                            _board[i, _board.Rows.Count - 1].Style.BackColor = Color.LightGray;
                        }
                    }


                }
            }
            foreach (var exam_Conflit in _host.GetScheduledExams().Where(ex => ex.Key.Season == season))
            {
                int colIndex;
                for (colIndex = 1; colIndex < _board.Columns.Count; colIndex++)
                {
                    if ((((DateTime)_board.Columns[colIndex].Tag).Day == exam_Conflit.Key.ExamDate.Day) &&
                        (((DateTime)_board.Columns[colIndex].Tag).Month == exam_Conflit.Key.ExamDate.Month) &&
                        (((DateTime)_board.Columns[colIndex].Tag).Year == exam_Conflit.Key.ExamDate.Year))
                    {
                        break;
                    }
                }
                int rowIndex;
                for (rowIndex = 1; rowIndex < _board.Rows.Count; rowIndex++)
                {
                    if ((((CUnit)_board.Rows[rowIndex].Tag) != null && ((CUnit)_board.Rows[rowIndex].Tag).Acronym == exam_Conflit.Key.CUnit.Acronym))
                    {
                        break;
                    }
                }
                _board[colIndex, rowIndex].Tag = exam_Conflit.Key;
                _board[colIndex, rowIndex].Value = exam_Conflit.Key.ExamDate.ToString("HH:mm");
                _exam_cell.Add(exam_Conflit.Key, _board[colIndex, rowIndex]);
                _allConflitList.AddRange(exam_Conflit.Value);
            }
            foreach (var exam in _exam_cell.Keys)
            {
                PaintCellBackgroung(exam);
            }
            this.ResumeLayout();
        }
        /// <summary>
        /// Paints conflits on textbox
        /// </summary>
        private void LogTextboxRefresh()
        {
            //PaintCellBackgroung();
            if (_currentExam != null && _host.GetScheduledExams().ContainsKey(_currentExam))
            {
                _currentExamConflitsDataSource.DataSource = null;
                _currentExamConflitsDataSource.DataSource = _host.GetExamConflits(_currentExam);
                _allConflitsDataSource.DataSource = null;
                _allConflitsDataSource.DataSource = _host.GetAllConflits().ToList();
                _dgv_allConflits.Update();
                BindingList<IRoom> rooms = new BindingList<IRoom>();
                foreach (var item in _currentExam.Rooms)
                {
                    rooms.Add(item.Room);
                }
                _currentExamRoomsSelectedDataSource.DataSource = null;
                _currentExamRoomsSelectedDataSource.DataSource = rooms;

            }
            else
            {
                _currentExamConflitsDataSource.DataSource = null;
                _currentExamRoomsSelectedDataSource.DataSource = null;
            }
        }

        private void UnPaintCellBackgroung(IExam ex)
        {
            if (_host.GetExamConflits(ex) == null) return;
            if (_host.GetExamConflits(ex).Count == 0)
            {
                if (((DateTime)_board.Columns[_exam_cell[ex].ColumnIndex].Tag).DayOfWeek == DayOfWeek.Sunday ||
                       ((DateTime)_board.Columns[_exam_cell[ex].ColumnIndex].Tag).DayOfWeek == DayOfWeek.Saturday)
                    _exam_cell[ex].Style.BackColor = Color.LightGray;
                else
                {
                    _exam_cell[ex].Style.BackColor = Color.White;
                }
            }
            foreach (var examConflit in _host.GetExamConflits(ex))
            {
                foreach (var exam in examConflit.Exams)
                {
                    if (exam == ex)
                    {
                        if (((DateTime)_board.Columns[_exam_cell[exam].ColumnIndex].Tag).DayOfWeek == DayOfWeek.Sunday ||
                            ((DateTime)_board.Columns[_exam_cell[exam].ColumnIndex].Tag).DayOfWeek == DayOfWeek.Saturday)
                            _exam_cell[exam].Style.BackColor = Color.LightGray;
                        else
                            _exam_cell[exam].Style.BackColor = Color.White;
                    }
                    else
                    //if (_host.GetExamConflits(exam).Count > 1 && _host.GetScheduledExams().Count > 1)
                    {
                        PaintCellBackgroudSingleExam(exam);
                    }
                }
            }
            UnPaintUC(ex);
        }

        private void PaintUC(IExam exam)
        {
            _board[0, _exam_cell[exam].RowIndex].Style.BackColor = Color.LightGreen;
        }

        private void UnPaintUC(IExam exam)
        {
            _board[0, _exam_cell[exam].RowIndex].Style.BackColor = Color.White;
        }


        private void PaintCellBackgroudSingleExam(IExam exam)
        {
            IConflict theConflit = null;
            int max = 0;
            foreach (var conflit in _host.GetExamConflits(exam))
            {
                if (conflit.Exams.Contains(_currentExam))
                {
                    _exam_cell[exam].Style.BackColor = Color.White;
                    continue;
                }
                theConflit = conflit;
                if (((int)conflit.Weight) > max) max = (int)conflit.Weight;
                if (conflit.Weight == ConflictWeight.Impossible) break;
            }
            if (theConflit == null) return;
            switch ((ConflictWeight)max)
            {
                case ConflictWeight.Minimal:
                    _exam_cell[exam].Style.BackColor = Color.Yellow;
                    break;
                case ConflictWeight.Medium:
                    _exam_cell[exam].Style.BackColor = Color.Yellow;
                    break;
                case ConflictWeight.Serious:
                    _exam_cell[exam].Style.BackColor = Color.Orange;
                    break;
                case ConflictWeight.Critical:
                    _exam_cell[exam].Style.BackColor = Color.PaleVioletRed;
                    break;
                case ConflictWeight.Impossible:
                    _exam_cell[exam].Style.BackColor = Color.Red;
                    break;
            }
        }

        private void PaintCellBackgroung(IExam ex)
        {
            List<IConflict> confs = _host.GetExamConflits(ex) ;
            if (confs == null) return;
            //if (confs.Count == 0)
            //{ 
            //    UnPaintCellBackgroung(ex);
            //    return;
            //}
            foreach (var conflit in confs.OrderBy(confw => confw.Weight))
            {
            switch (conflit.Weight)
                {
                    case ConflictWeight.Minimal:
                        foreach (var exam in conflit.Exams)
                        {
                            _exam_cell[exam].Style.BackColor = Color.LightYellow;
                        }
                        break;
                    case ConflictWeight.Medium:
                        foreach (var exam in conflit.Exams)
                        {
                            _exam_cell[exam].Style.BackColor = Color.Yellow;
                        }
                        break;
                    case ConflictWeight.Serious:
                        foreach (var exam in conflit.Exams)
                        {
                            _exam_cell[exam].Style.BackColor = Color.Orange;
                        }
                        break;
                    case ConflictWeight.Critical:
                        foreach (var exam in conflit.Exams)
                        {
                            _exam_cell[exam].Style.BackColor = Color.PaleVioletRed;
                        }
                        break;
                    case ConflictWeight.Impossible:
                        foreach (var exam in conflit.Exams)
                        {
                            _exam_cell[exam].Style.BackColor = Color.Red;
                        }
                        break;
                }
            }
            PaintUC(ex);
        }

        private void Board_CellClick(object sender, DataGridViewCellEventArgs e)
        {
            if (e.ColumnIndex < 0 || e.RowIndex < 0) return;
            _currentExam = _board[e.ColumnIndex, e.RowIndex].Tag as Exam;
            LogTextboxRefresh();
            SelectExamsWithConflits(_currentExam);
        }

        private void SelectExamsWithConflits(IExam exam)
        {
            if(exam == null) return;
            foreach (var examConflit in _host.GetExamConflits(exam))
            {
                _exam_cell[exam].Selected = true;
                foreach (var innerExam in examConflit.Exams)
                {
                    if(innerExam == exam) continue;
                    _exam_cell[innerExam].Selected = true;
                }
            }
        }

        private void Board_CellMouseMove(object sender, DataGridViewCellMouseEventArgs e)
        {
            if (e.ColumnIndex < 0 || e.RowIndex < 0) return;
            if (_board[e.ColumnIndex, e.RowIndex].Tag == null)
            {
                _board[e.ColumnIndex, e.RowIndex].ToolTipText = "";
                return;
            }
            List<IConflict> tmp;
            if (!_host.GetScheduledExams().TryGetValue(((Exam)_board[e.ColumnIndex, e.RowIndex].Tag), out tmp)) return;
            if (tmp == null) return;
            _board[e.ColumnIndex, e.RowIndex].ToolTipText = "";
            foreach (var conflit in tmp)
            {
                if (conflit == null) continue;
                _board[e.ColumnIndex, e.RowIndex].ToolTipText = _board[e.ColumnIndex, e.RowIndex].ToolTipText + conflit.ConflitcInfo + "\r\n";
            }
        }

        private void Board_CellDoubleClick(object sender, DataGridViewCellEventArgs e)
        {
            if (e.ColumnIndex <= 0 || e.RowIndex <= 0) return;
            //Verifica se o click foi em zona válida
            if (_board.Rows[e.RowIndex].Tag as CUnit == null) return;
            //Remove o exame
            if (_board[e.ColumnIndex, e.RowIndex].Tag != null)
            {
                UnScheduleExam(e);
            }
            else
            {
                ScheduleExam(e);
            }

            #region TODELETE

            //--------------------------------------------------------------------------------------------------------
            //Ir à Unit of work buscar a UC atencao que o id da UC não é o acronimo, tornar elegante

            //CUnit s = (CUnit)_board.Rows[e.RowIndex].Tag;//MapperControl.GetAllCUnit().Where(cu => cu.Acronym.Equals(_board[0, e.RowIndex].Value)).First();
            //--------------------------------------------------------------------------------------------------------
            //Verifica se existe exame marcado naquela cell se houver remove do dicionario checked, futuramente elimina todos 
            //os conflito provocado por esta marcação


            /*_checked.Remove(ex);
            //Na lista de exames
            foreach (var exam in _checked.Keys)
            {
                //Criar lista temp para depois remover 
                List<IConflit> conflitsToRemove = new List<IConflit>();
                //ve os conflitos
                foreach (var conflit in _checked[exam])
                {
                    if (conflit == null) continue;
                    //se o conflito tiver o exame adicionar esse exame
                    if (conflit.Exams.Contains(ex))
                    {
                        conflitsToRemove.Add(conflit);
                        //_allConflitsDataSource.Remove(conflit);
                        _allConflitList.Remove(conflit);
                    }
                }
                //remove todos os conflitos que adicionados anteriormente
                _checked[exam].RemoveAll(conflitsToRemove.Contains);
            }*/

            #endregion

            //---------------------------------------------------------------------------------------------------------
            //Cria um exame e adiciona à lista _pending(exames pendentes de validação)
            /* var tmp = new Exam
             {
                 CUnit =
                     MapperControl.GetAllCUnit().Where(cu => cu.Acronym.Equals(_board[0, e.RowIndex].Value))
                     .First(),
                 ExamDate = (DateTime)_board.Columns[e.ColumnIndex].Tag,
                 ExamEndDate = ((DateTime)_board.Columns[e.ColumnIndex].Tag).AddHours(3)     // _days[e.ColumnIndex - 1]

             };*/

            //LogTextboxRefresh();
        }

        private void ScheduleExam(DataGridViewCellEventArgs e)
        {
            IExam exam = _host.GetUnscheduledExam((ICUnit)_board.Rows[e.RowIndex].Tag,
                                     (IExamSeason)_cbx_seasonSelection.SelectedItem);
            if (exam == null)
            {
                foreach (var exa in _exam_cell.Keys)
                {
                    if(exa.CUnit == _board.Rows[e.RowIndex].Tag){ exam = exa;
                        break;
                    }
                }
                UnScheduleExam(new DataGridViewCellEventArgs(_exam_cell[exam].ColumnIndex, _exam_cell[exam].RowIndex));
                //MessageBox.Show("Exame já marcado.");
                //return;
            }

            exam.ExamDate = (DateTime)_board.Columns[e.ColumnIndex].Tag;
            exam.ExamEndDate = ((DateTime)_board.Columns[e.ColumnIndex].Tag).AddHours(3);
            _pending.Add(exam);
            //-----------------------------------------------------------------------------------------------------------
            //associa o exame à célula
            _board[e.ColumnIndex, e.RowIndex].Tag = exam;
            _currentExam = exam;
            _exam_cell.Add(exam, _board[e.ColumnIndex, e.RowIndex]);
            //------------------------------------------------------------------------------------------------------------
            //verifica se a background worker está activa se n esta executa-a
           // if (!_bgw.IsBusy) _bgw.RunWorkerAsync();
            //------------------------------------------------------------------------------------------------------------
            //else
            //{
                lock (_pending)
                {
                    Monitor.Pulse(_pending);
                }
            //}
            _board[e.ColumnIndex, e.RowIndex].Value = _board[e.ColumnIndex, e.RowIndex].Value != null ? null : exam.ExamDate.ToString("HH:mm");
        }

        private void UnScheduleExam(DataGridViewCellEventArgs e)
        {
            IExam ex = (IExam)_board[e.ColumnIndex, e.RowIndex].Tag;
            //TODO: Review
            _currentExam = ex;
            if (_pending.Contains(ex))
            {
                UnPaintCellBackgroung(ex);
                _pending.Remove(ex);
                _exam_cell.Remove(ex);
                _board[e.ColumnIndex, e.RowIndex].Value = null;
                _board[e.ColumnIndex, e.RowIndex].Tag = null;
                _currentExam = null;
            }
            else
            {
                UnPaintCellBackgroung(ex);
                List<IConflict> lconf = _host.RemoveExam(ex);
                if (lconf == null)
                {
                    MessageBox.Show("Exame em processamento, neste momento não pode ser removido");
                    PaintCellBackgroung(ex);
                    return;
                }
                foreach (var item in lconf)
                {
                    _allConflitsDataSource.Remove(item);
                }
               // _allConflitList.RemoveAll(lconf.Contains);
            }
            _exam_cell.Remove(ex);
            _board[e.ColumnIndex, e.RowIndex].Value = null;
            _board[e.ColumnIndex, e.RowIndex].Tag = null;
            _currentExam = null;
            LogTextboxRefresh();
            return;
        }

        private void _cbx_seasonSelection_SelectedIndexChanged(object sender, EventArgs e)
        {
            ExamSeason season = _cbx_seasonSelection.SelectedItem as ExamSeason;
            if (season != null)
            {
                PaintBoard(season);
            }
        }

        private void _board_CellMouseDown(object sender, DataGridViewCellMouseEventArgs e)
        {
            if (e.Button == MouseButtons.Right)
            {
                //check if is valid cell
                if (e.RowIndex <= 0 || e.ColumnIndex <= 0) { _board.CurrentCell = null; return; }
                if (_board.Rows[e.RowIndex].Tag == null) return;// _board.CurrentCell = null;
                //select cell
                _board.CurrentCell = _board[e.ColumnIndex, e.RowIndex];
                //schedule exam ifs not
                //_board.ContextMenuStrip.Show(_board, e.Location);
            }

        }

        private void _ctxmenu_exams_Opening(object sender, CancelEventArgs e)
        {
            if (_board.CurrentCell == null) { e.Cancel = true; return; }
            if (_board.CurrentCell.RowIndex <= 0 || _board.CurrentCell.ColumnIndex <= 0) { e.Cancel = true; return; }
            if (_board.Rows[_board.CurrentCell.RowIndex].Tag == null) { e.Cancel = true; return; }
        }

        private void _tsm_scheduleDate_Click(object sender, EventArgs e)
        {
            IExam exam = _board.CurrentCell.Tag as IExam;
            if (exam != null)
            {
                ExamDateScheduler scheduler = new ExamDateScheduler(exam);
                if (DialogResult.OK == scheduler.ShowDialog())
                {
                    UnPaintCellBackgroung(exam);
                    _pending.Add(exam);
                    lock (_pending)
                    {
                        Monitor.Pulse(_pending);
                    }
                }
                _exam_cell[exam].Value = exam.ExamDate.ToString("HH:mm");
                LogTextboxRefresh();
            }
        }

        private void _tsm_defineRoom_Click(object sender, EventArgs e)
        {
            Exam exam = _board.CurrentCell.Tag as Exam;
            if (exam != null)
            {
                ExamRoomDefiner roomDefiner = new ExamRoomDefiner(exam, _host);
                roomDefiner.ShowDialog();
                LogTextboxRefresh();
            }

        }

        private void Board_FormClosing(object sender, FormClosingEventArgs e)
        {
            
            _host.SaveAllState();
        }


    }
}
